<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8"/>
    <title id="head-title">baogao.html</title>
      <link href="assets\style.css" rel="stylesheet" type="text/css"/>
  </head>
  <body>
    <h1 id="title">baogao.html</h1>
    <p>Report generated on 10-Jul-2025 at 11:03:31 by <a href="https://pypi.python.org/pypi/pytest-html">pytest-html</a>
        v4.1.1</p>
    <div id="environment-header">
      <h2>Environment</h2>
    </div>
    <table id="environment"></table>
    <!-- TEMPLATES -->
      <template id="template_environment_row">
      <tr>
        <td></td>
        <td></td>
      </tr>
    </template>
    <template id="template_results-table__body--empty">
      <tbody class="results-table-row">
        <tr id="not-found-message">
          <td colspan="4">No results found. Check the filters.</th>
        </tr>
    </template>
    <template id="template_results-table__tbody">
      <tbody class="results-table-row">
        <tr class="collapsible">
        </tr>
        <tr class="extras-row">
          <td class="extra" colspan="4">
            <div class="extraHTML"></div>
            <div class="media">
              <div class="media-container">
                  <div class="media-container__nav--left"><</div>
                  <div class="media-container__viewport">
                    <img src="" />
                    <video controls>
                      <source src="" type="video/mp4">
                    </video>
                  </div>
                  <div class="media-container__nav--right">></div>
                </div>
                <div class="media__name"></div>
                <div class="media__counter"></div>
            </div>
            <div class="logwrapper">
              <div class="logexpander"></div>
              <div class="log"></div>
            </div>
          </td>
        </tr>
      </tbody>
    </template>
    <!-- END TEMPLATES -->
    <div class="summary">
      <div class="summary__data">
        <h2>Summary</h2>
        <div class="additional-summary prefix">
        </div>
        <p class="run-count">0 test took 00:00:26.</p>
        <p class="filter">(Un)check the boxes to filter the results.</p>
        <div class="summary__reload">
          <div class="summary__reload__button hidden" onclick="location.reload()">
            <div>There are still tests running. <br />Reload this page to get the latest results!</div>
          </div>
        </div>
        <div class="summary__spacer"></div>
        <div class="controls">
          <div class="filters">
            <input checked="true" class="filter" name="filter_checkbox" type="checkbox" data-test-result="failed" disabled/>
            <span class="failed">0 Failed,</span>
            <input checked="true" class="filter" name="filter_checkbox" type="checkbox" data-test-result="passed" disabled/>
            <span class="passed">0 Passed,</span>
            <input checked="true" class="filter" name="filter_checkbox" type="checkbox" data-test-result="skipped" disabled/>
            <span class="skipped">0 Skipped,</span>
            <input checked="true" class="filter" name="filter_checkbox" type="checkbox" data-test-result="xfailed" disabled/>
            <span class="xfailed">0 Expected failures,</span>
            <input checked="true" class="filter" name="filter_checkbox" type="checkbox" data-test-result="xpassed" disabled/>
            <span class="xpassed">0 Unexpected passes,</span>
            <input checked="true" class="filter" name="filter_checkbox" type="checkbox" data-test-result="error" />
            <span class="error">3 Errors,</span>
            <input checked="true" class="filter" name="filter_checkbox" type="checkbox" data-test-result="rerun" disabled/>
            <span class="rerun">0 Reruns</span>
          </div>
          <div class="collapse">
            <button id="show_all_details">Show all details</button>&nbsp;/&nbsp;<button id="hide_all_details">Hide all details</button>
          </div>
        </div>
      </div>
      <div class="additional-summary summary">
      </div>
      <div class="additional-summary postfix">
      </div>
    </div>
    <table id="results-table">
      <thead id="results-table-head">
        <tr>
          <th class="sortable" data-column-type="result">Result</th>
          <th class="sortable" data-column-type="testId">Test</th>
          <th class="sortable" data-column-type="duration">Duration</th>
          <th>Links</th>
        </tr>
      </thead>
    </table>
  </body>
  <footer>
    <div id="data-container" data-jsonblob="{&#34;environment&#34;: {&#34;Python&#34;: &#34;3.8.0&#34;, &#34;Platform&#34;: &#34;Windows-10-10.0.22621-SP0&#34;, &#34;Packages&#34;: {&#34;pytest&#34;: &#34;8.3.5&#34;, &#34;pluggy&#34;: &#34;1.5.0&#34;}, &#34;Plugins&#34;: {&#34;html&#34;: &#34;4.1.1&#34;, &#34;metadata&#34;: &#34;3.1.1&#34;, &#34;anyio&#34;: &#34;4.5.2&#34;}, &#34;JAVA_HOME&#34;: &#34;D:\\java\\17.0.12&#34;}, &#34;tests&#34;: {&#34;case/test_beijing.py::TestBeiJing::test_01&#34;: [{&#34;extras&#34;: [], &#34;result&#34;: &#34;Error&#34;, &#34;testId&#34;: &#34;case/test_beijing.py::TestBeiJing::test_01::setup&#34;, &#34;duration&#34;: &#34;00:00:09&#34;, &#34;resultsTableRow&#34;: [&#34;&lt;td class=\&#34;col-result\&#34;&gt;Error&lt;/td&gt;&#34;, &#34;&lt;td class=\&#34;col-testId\&#34;&gt;case/test_beijing.py::TestBeiJing::test_01::setup&lt;/td&gt;&#34;, &#34;&lt;td class=\&#34;col-duration\&#34;&gt;00:00:09&lt;/td&gt;&#34;, &#34;&lt;td class=\&#34;col-links\&#34;&gt;&lt;/td&gt;&#34;], &#34;log&#34;: &#34;self = &amp;lt;urllib3.connection.HTTPConnection object at 0x000001BE6AAB9370&amp;gt;\n\n    def _new_conn(self):\n        &amp;quot;&amp;quot;&amp;quot;Establish a socket connection and set nodelay settings on it.\n    \n        :return: New socket connection.\n        &amp;quot;&amp;quot;&amp;quot;\n        extra_kw = {}\n        if self.source_address:\n            extra_kw[&amp;quot;source_address&amp;quot;] = self.source_address\n    \n        if self.socket_options:\n            extra_kw[&amp;quot;socket_options&amp;quot;] = self.socket_options\n    \n        try:\n&amp;gt;           conn = connection.create_connection(\n                (self._dns_host, self.port), self.timeout, **extra_kw\n            )\n\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\connection.py:174: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\util\\connection.py:95: in create_connection\n    raise err\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _\n\naddress = (&amp;#x27;127.0.0.1&amp;#x27;, 4723), timeout = None, source_address = None\nsocket_options = [(6, 1, 1)]\n\n    def create_connection(\n        address,\n        timeout=socket._GLOBAL_DEFAULT_TIMEOUT,\n        source_address=None,\n        socket_options=None,\n    ):\n        &amp;quot;&amp;quot;&amp;quot;Connect to *address* and return the socket object.\n    \n        Convenience function.  Connect to *address* (a 2-tuple ``(host,\n        port)``) and return the socket object.  Passing the optional\n        *timeout* parameter will set the timeout on the socket instance\n        before attempting to connect.  If no *timeout* is supplied, the\n        global default timeout setting returned by :func:`socket.getdefaulttimeout`\n        is used.  If *source_address* is set it must be a tuple of (host, port)\n        for the socket to bind as a source address before making the connection.\n        An host of &amp;#x27;&amp;#x27; or port 0 tells the OS to use the default.\n        &amp;quot;&amp;quot;&amp;quot;\n    \n        host, port = address\n        if host.startswith(&amp;quot;[&amp;quot;):\n            host = host.strip(&amp;quot;[]&amp;quot;)\n        err = None\n    \n        # Using the value from allowed_gai_family() in the context of getaddrinfo lets\n        # us select whether to work with IPv4 DNS records, IPv6 records, or both.\n        # The original create_connection function always returns all records.\n        family = allowed_gai_family()\n    \n        try:\n            host.encode(&amp;quot;idna&amp;quot;)\n        except UnicodeError:\n            return six.raise_from(\n                LocationParseError(u&amp;quot;&amp;#x27;%s&amp;#x27;, label empty or too long&amp;quot; % host), None\n            )\n    \n        for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):\n            af, socktype, proto, canonname, sa = res\n            sock = None\n            try:\n                sock = socket.socket(af, socktype, proto)\n    \n                # If provided, set socket level options before connecting.\n                _set_socket_options(sock, socket_options)\n    \n                if timeout is not socket._GLOBAL_DEFAULT_TIMEOUT:\n                    sock.settimeout(timeout)\n                if source_address:\n                    sock.bind(source_address)\n&amp;gt;               sock.connect(sa)\nE               ConnectionRefusedError: [WinError 10061] \u7531\u4e8e\u76ee\u6807\u8ba1\u7b97\u673a\u79ef\u6781\u62d2\u7edd\uff0c\u65e0\u6cd5\u8fde\u63a5\u3002\n\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\util\\connection.py:85: ConnectionRefusedError\n\nDuring handling of the above exception, another exception occurred:\n\nself = &amp;lt;urllib3.connectionpool.HTTPConnectionPool object at 0x000001BE6AA9D130&amp;gt;\nmethod = &amp;#x27;POST&amp;#x27;, url = &amp;#x27;/wd/hub/session&amp;#x27;\nbody = &amp;#x27;{&amp;quot;capabilities&amp;quot;: {&amp;quot;alwaysMatch&amp;quot;: {&amp;quot;platformName&amp;quot;: &amp;quot;Android&amp;quot;, &amp;quot;appium:deviceName&amp;quot;: &amp;quot;emulator-5554&amp;quot;, &amp;quot;appium:noReset&amp;quot;: ...&amp;quot;: true, &amp;quot;appPackage&amp;quot;: &amp;quot;cn.xuexi.android&amp;quot;, &amp;quot;appActivity&amp;quot;: &amp;quot;com.alibaba.android.rimet.biz.home.activity.HomeActivity&amp;quot;}}&amp;#x27;\nheaders = {&amp;#x27;Accept&amp;#x27;: &amp;#x27;application/json&amp;#x27;, &amp;#x27;Connection&amp;#x27;: &amp;#x27;keep-alive&amp;#x27;, &amp;#x27;Content-Type&amp;#x27;: &amp;#x27;application/json;charset=UTF-8&amp;#x27;, &amp;#x27;User-Agent&amp;#x27;: &amp;#x27;appium/python 2.0.0 (selenium/4.0.0 (python windows))&amp;#x27;, ...}\nretries = Retry(total=0, connect=None, read=None, redirect=None, status=None)\nredirect = False, assert_same_host = False\ntimeout = &amp;lt;object object at 0x000001BE6A35BEB0&amp;gt;, pool_timeout = None\nrelease_conn = True, chunked = False, body_pos = None\nresponse_kw = {&amp;#x27;request_url&amp;#x27;: &amp;#x27;http://127.0.0.1:4723/wd/hub/session&amp;#x27;}\nparsed_url = Url(scheme=None, auth=None, host=None, port=None, path=&amp;#x27;/wd/hub/session&amp;#x27;, query=None, fragment=None)\ndestination_scheme = None, conn = None, release_this_conn = True\nhttp_tunnel_required = False, err = None, clean_exit = False\n\n    def urlopen(\n        self,\n        method,\n        url,\n        body=None,\n        headers=None,\n        retries=None,\n        redirect=True,\n        assert_same_host=True,\n        timeout=_Default,\n        pool_timeout=None,\n        release_conn=None,\n        chunked=False,\n        body_pos=None,\n        **response_kw\n    ):\n        &amp;quot;&amp;quot;&amp;quot;\n        Get a connection from the pool and perform an HTTP request. This is the\n        lowest level call for making a request, so you&amp;#x27;ll need to specify all\n        the raw details.\n    \n        .. note::\n    \n           More commonly, it&amp;#x27;s appropriate to use a convenience method provided\n           by :class:`.RequestMethods`, such as :meth:`request`.\n    \n        .. note::\n    \n           `release_conn` will only behave as expected if\n           `preload_content=False` because we want to make\n           `preload_content=False` the default behaviour someday soon without\n           breaking backwards compatibility.\n    \n        :param method:\n            HTTP request method (such as GET, POST, PUT, etc.)\n    \n        :param url:\n            The URL to perform the request on.\n    \n        :param body:\n            Data to send in the request body, either :class:`str`, :class:`bytes`,\n            an iterable of :class:`str`/:class:`bytes`, or a file-like object.\n    \n        :param headers:\n            Dictionary of custom headers to send, such as User-Agent,\n            If-None-Match, etc. If None, pool headers are used. If provided,\n            these headers completely replace any pool-specific headers.\n    \n        :param retries:\n            Configure the number of retries to allow before raising a\n            :class:`~urllib3.exceptions.MaxRetryError` exception.\n    \n            Pass ``None`` to retry until you receive a response. Pass a\n            :class:`~urllib3.util.retry.Retry` object for fine-grained control\n            over different types of retries.\n            Pass an integer number to retry connection errors that many times,\n            but no other types of errors. Pass zero to never retry.\n    \n            If ``False``, then retries are disabled and any exception is raised\n            immediately. Also, instead of raising a MaxRetryError on redirects,\n            the redirect response will be returned.\n    \n        :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.\n    \n        :param redirect:\n            If True, automatically handle redirects (status codes 301, 302,\n            303, 307, 308). Each redirect counts as a retry. Disabling retries\n            will disable redirect, too.\n    \n        :param assert_same_host:\n            If ``True``, will make sure that the host of the pool requests is\n            consistent else will raise HostChangedError. When ``False``, you can\n            use the pool on an HTTP proxy and request foreign hosts.\n    \n        :param timeout:\n            If specified, overrides the default timeout for this one\n            request. It may be a float (in seconds) or an instance of\n            :class:`urllib3.util.Timeout`.\n    \n        :param pool_timeout:\n            If set and the pool is set to block=True, then this method will\n            block for ``pool_timeout`` seconds and raise EmptyPoolError if no\n            connection is available within the time period.\n    \n        :param release_conn:\n            If False, then the urlopen call will not release the connection\n            back into the pool once a response is received (but will release if\n            you read the entire contents of the response such as when\n            `preload_content=True`). This is useful if you&amp;#x27;re not preloading\n            the response&amp;#x27;s content immediately. You will need to call\n            ``r.release_conn()`` on the response ``r`` to return the connection\n            back into the pool. If None, it takes the value of\n            ``response_kw.get(&amp;#x27;preload_content&amp;#x27;, True)``.\n    \n        :param chunked:\n            If True, urllib3 will send the body using chunked transfer\n            encoding. Otherwise, urllib3 will send the body using the standard\n            content-length form. Defaults to False.\n    \n        :param int body_pos:\n            Position to seek to in file-like body in the event of a retry or\n            redirect. Typically this won&amp;#x27;t need to be set because urllib3 will\n            auto-populate the value when needed.\n    \n        :param \\\\**response_kw:\n            Additional parameters are passed to\n            :meth:`urllib3.response.HTTPResponse.from_httplib`\n        &amp;quot;&amp;quot;&amp;quot;\n    \n        parsed_url = parse_url(url)\n        destination_scheme = parsed_url.scheme\n    \n        if headers is None:\n            headers = self.headers\n    \n        if not isinstance(retries, Retry):\n            retries = Retry.from_int(retries, redirect=redirect, default=self.retries)\n    \n        if release_conn is None:\n            release_conn = response_kw.get(&amp;quot;preload_content&amp;quot;, True)\n    \n        # Check host\n        if assert_same_host and not self.is_same_host(url):\n            raise HostChangedError(self, url, retries)\n    \n        # Ensure that the URL we&amp;#x27;re connecting to is properly encoded\n        if url.startswith(&amp;quot;/&amp;quot;):\n            url = six.ensure_str(_encode_target(url))\n        else:\n            url = six.ensure_str(parsed_url.url)\n    \n        conn = None\n    \n        # Track whether `conn` needs to be released before\n        # returning/raising/recursing. Update this variable if necessary, and\n        # leave `release_conn` constant throughout the function. That way, if\n        # the function recurses, the original value of `release_conn` will be\n        # passed down into the recursive call, and its value will be respected.\n        #\n        # See issue #651 [1] for details.\n        #\n        # [1] &amp;lt;https://github.com/urllib3/urllib3/issues/651&amp;gt;\n        release_this_conn = release_conn\n    \n        http_tunnel_required = connection_requires_http_tunnel(\n            self.proxy, self.proxy_config, destination_scheme\n        )\n    \n        # Merge the proxy headers. Only done when not using HTTP CONNECT. We\n        # have to copy the headers dict so we can safely change it without those\n        # changes being reflected in anyone else&amp;#x27;s copy.\n        if not http_tunnel_required:\n            headers = headers.copy()\n            headers.update(self.proxy_headers)\n    \n        # Must keep the exception bound to a separate variable or else Python 3\n        # complains about UnboundLocalError.\n        err = None\n    \n        # Keep track of whether we cleanly exited the except block. This\n        # ensures we do proper cleanup in finally.\n        clean_exit = False\n    \n        # Rewind body position, if needed. Record current position\n        # for future rewinds in the event of a redirect/retry.\n        body_pos = set_file_position(body, body_pos)\n    \n        try:\n            # Request a connection from the queue.\n            timeout_obj = self._get_timeout(timeout)\n            conn = self._get_conn(timeout=pool_timeout)\n    \n            conn.timeout = timeout_obj.connect_timeout\n    \n            is_new_proxy_conn = self.proxy is not None and not getattr(\n                conn, &amp;quot;sock&amp;quot;, None\n            )\n            if is_new_proxy_conn and http_tunnel_required:\n                self._prepare_proxy(conn)\n    \n            # Make the request on the httplib connection object.\n&amp;gt;           httplib_response = self._make_request(\n                conn,\n                method,\n                url,\n                timeout=timeout_obj,\n                body=body,\n                headers=headers,\n                chunked=chunked,\n            )\n\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\connectionpool.py:716: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\connectionpool.py:416: in _make_request\n    conn.request(method, url, **httplib_request_kw)\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\connection.py:244: in request\n    super(HTTPConnection, self).request(method, url, body=body, headers=headers)\nC:\\Program Files\\Python38\\lib\\http\\client.py:1230: in request\n    self._send_request(method, url, body, headers, encode_chunked)\nC:\\Program Files\\Python38\\lib\\http\\client.py:1276: in _send_request\n    self.endheaders(body, encode_chunked=encode_chunked)\nC:\\Program Files\\Python38\\lib\\http\\client.py:1225: in endheaders\n    self._send_output(message_body, encode_chunked=encode_chunked)\nC:\\Program Files\\Python38\\lib\\http\\client.py:1004: in _send_output\n    self.send(msg)\nC:\\Program Files\\Python38\\lib\\http\\client.py:944: in send\n    self.connect()\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\connection.py:205: in connect\n    conn = self._new_conn()\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _\n\nself = &amp;lt;urllib3.connection.HTTPConnection object at 0x000001BE6AAB9370&amp;gt;\n\n    def _new_conn(self):\n        &amp;quot;&amp;quot;&amp;quot;Establish a socket connection and set nodelay settings on it.\n    \n        :return: New socket connection.\n        &amp;quot;&amp;quot;&amp;quot;\n        extra_kw = {}\n        if self.source_address:\n            extra_kw[&amp;quot;source_address&amp;quot;] = self.source_address\n    \n        if self.socket_options:\n            extra_kw[&amp;quot;socket_options&amp;quot;] = self.socket_options\n    \n        try:\n            conn = connection.create_connection(\n                (self._dns_host, self.port), self.timeout, **extra_kw\n            )\n    \n        except SocketTimeout:\n            raise ConnectTimeoutError(\n                self,\n                &amp;quot;Connection to %s timed out. (connect timeout=%s)&amp;quot;\n                % (self.host, self.timeout),\n            )\n    \n        except SocketError as e:\n&amp;gt;           raise NewConnectionError(\n                self, &amp;quot;Failed to establish a new connection: %s&amp;quot; % e\n            )\nE           urllib3.exceptions.NewConnectionError: &amp;lt;urllib3.connection.HTTPConnection object at 0x000001BE6AAB9370&amp;gt;: Failed to establish a new connection: [WinError 10061] \u7531\u4e8e\u76ee\u6807\u8ba1\u7b97\u673a\u79ef\u6781\u62d2\u7edd\uff0c\u65e0\u6cd5\u8fde\u63a5\u3002\n\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\connection.py:186: NewConnectionError\n\nDuring handling of the above exception, another exception occurred:\n\nself = &amp;lt;test_beijing.TestBeiJing object at 0x000001BE6A263520&amp;gt;\n\n    def setup_method(self):\n        logging.info(&amp;#x27;\u5b9e\u4f8b\u5316\u5317\u4eac\u9875\u9762\u7c7b&amp;#x27;)\n&amp;gt;       self.po=BeiJingPage()\n\ncase\\test_beijing.py:7: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _\nbase.py:18: in __init__\n    self.driver=webdriver.Remote(&amp;#x27;http://127.0.0.1:4723/wd/hub&amp;#x27;,cap)\nC:\\Program Files\\Python38\\lib\\site-packages\\appium\\webdriver\\webdriver.py:273: in __init__\n    super().__init__(\nC:\\Program Files\\Python38\\lib\\site-packages\\selenium\\webdriver\\remote\\webdriver.py:266: in __init__\n    self.start_session(capabilities, browser_profile)\nC:\\Program Files\\Python38\\lib\\site-packages\\appium\\webdriver\\webdriver.py:364: in start_session\n    response = self.execute(RemoteCommand.NEW_SESSION, parameters)\nC:\\Program Files\\Python38\\lib\\site-packages\\selenium\\webdriver\\remote\\webdriver.py:416: in execute\n    response = self.command_executor.execute(driver_command, params)\nC:\\Program Files\\Python38\\lib\\site-packages\\selenium\\webdriver\\remote\\remote_connection.py:398: in execute\n    return self._request(command_info[0], url, body=data)\nC:\\Program Files\\Python38\\lib\\site-packages\\selenium\\webdriver\\remote\\remote_connection.py:420: in _request\n    resp = self._conn.request(method, url, body=body, headers=headers)\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\request.py:81: in request\n    return self.request_encode_body(\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\request.py:173: in request_encode_body\n    return self.urlopen(method, url, **extra_kw)\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\poolmanager.py:376: in urlopen\n    response = conn.urlopen(method, u.request_uri, **kw)\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\connectionpool.py:830: in urlopen\n    return self.urlopen(\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\connectionpool.py:830: in urlopen\n    return self.urlopen(\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\connectionpool.py:830: in urlopen\n    return self.urlopen(\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\connectionpool.py:802: in urlopen\n    retries = retries.increment(\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _\n\nself = Retry(total=0, connect=None, read=None, redirect=None, status=None)\nmethod = &amp;#x27;POST&amp;#x27;, url = &amp;#x27;/wd/hub/session&amp;#x27;, response = None\nerror = NewConnectionError(&amp;#x27;&amp;lt;urllib3.connection.HTTPConnection object at 0x000001BE6AAB9370&amp;gt;: Failed to establish a new connection: [WinError 10061] \u7531\u4e8e\u76ee\u6807\u8ba1\u7b97\u673a\u79ef\u6781\u62d2\u7edd\uff0c\u65e0\u6cd5\u8fde\u63a5\u3002&amp;#x27;)\n_pool = &amp;lt;urllib3.connectionpool.HTTPConnectionPool object at 0x000001BE6AA9D130&amp;gt;\n_stacktrace = &amp;lt;traceback object at 0x000001BE6AAC6C00&amp;gt;\n\n    def increment(\n        self,\n        method=None,\n        url=None,\n        response=None,\n        error=None,\n        _pool=None,\n        _stacktrace=None,\n    ):\n        &amp;quot;&amp;quot;&amp;quot;Return a new Retry object with incremented retry counters.\n    \n        :param response: A response object, or None, if the server did not\n            return a response.\n        :type response: :class:`~urllib3.response.HTTPResponse`\n        :param Exception error: An error encountered during the request, or\n            None if the response was received successfully.\n    \n        :return: A new ``Retry`` object.\n        &amp;quot;&amp;quot;&amp;quot;\n        if self.total is False and error:\n            # Disabled, indicate to re-raise the error.\n            raise six.reraise(type(error), error, _stacktrace)\n    \n        total = self.total\n        if total is not None:\n            total -= 1\n    \n        connect = self.connect\n        read = self.read\n        redirect = self.redirect\n        status_count = self.status\n        other = self.other\n        cause = &amp;quot;unknown&amp;quot;\n        status = None\n        redirect_location = None\n    \n        if error and self._is_connection_error(error):\n            # Connect retry?\n            if connect is False:\n                raise six.reraise(type(error), error, _stacktrace)\n            elif connect is not None:\n                connect -= 1\n    \n        elif error and self._is_read_error(error):\n            # Read retry?\n            if read is False or not self._is_method_retryable(method):\n                raise six.reraise(type(error), error, _stacktrace)\n            elif read is not None:\n                read -= 1\n    \n        elif error:\n            # Other retry?\n            if other is not None:\n                other -= 1\n    \n        elif response and response.get_redirect_location():\n            # Redirect retry?\n            if redirect is not None:\n                redirect -= 1\n            cause = &amp;quot;too many redirects&amp;quot;\n            redirect_location = response.get_redirect_location()\n            status = response.status\n    \n        else:\n            # Incrementing because of a server error like a 500 in\n            # status_forcelist and the given method is in the allowed_methods\n            cause = ResponseError.GENERIC_ERROR\n            if response and response.status:\n                if status_count is not None:\n                    status_count -= 1\n                cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)\n                status = response.status\n    \n        history = self.history + (\n            RequestHistory(method, url, error, status, redirect_location),\n        )\n    \n        new_retry = self.new(\n            total=total,\n            connect=connect,\n            read=read,\n            redirect=redirect,\n            status=status_count,\n            other=other,\n            history=history,\n        )\n    \n        if new_retry.is_exhausted():\n&amp;gt;           raise MaxRetryError(_pool, url, error or ResponseError(cause))\nE           urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host=&amp;#x27;127.0.0.1&amp;#x27;, port=4723): Max retries exceeded with url: /wd/hub/session (Caused by NewConnectionError(&amp;#x27;&amp;lt;urllib3.connection.HTTPConnection object at 0x000001BE6AAB9370&amp;gt;: Failed to establish a new connection: [WinError 10061] \u7531\u4e8e\u76ee\u6807\u8ba1\u7b97\u673a\u79ef\u6781\u62d2\u7edd\uff0c\u65e0\u6cd5\u8fde\u63a5\u3002&amp;#x27;))\n\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\util\\retry.py:594: MaxRetryError\n\n------------------------------ Captured log setup ------------------------------\nINFO     root:test_beijing.py:6 \u5b9e\u4f8b\u5316\u5317\u4eac\u9875\u9762\u7c7b\nDEBUG    selenium.webdriver.remote.remote_connection:remote_connection.py:412 POST http://127.0.0.1:4723/wd/hub/session {&amp;quot;capabilities&amp;quot;: {&amp;quot;alwaysMatch&amp;quot;: {&amp;quot;platformName&amp;quot;: &amp;quot;Android&amp;quot;, &amp;quot;appium:deviceName&amp;quot;: &amp;quot;emulator-5554&amp;quot;, &amp;quot;appium:noReset&amp;quot;: true, &amp;quot;appium:appPackage&amp;quot;: &amp;quot;cn.xuexi.android&amp;quot;, &amp;quot;appium:appActivity&amp;quot;: &amp;quot;com.alibaba.android.rimet.biz.home.activity.HomeActivity&amp;quot;}, &amp;quot;firstMatch&amp;quot;: [{}]}, &amp;quot;desiredCapabilities&amp;quot;: {&amp;quot;platformName&amp;quot;: &amp;quot;Android&amp;quot;, &amp;quot;deviceName&amp;quot;: &amp;quot;emulator-5554&amp;quot;, &amp;quot;noReset&amp;quot;: true, &amp;quot;appPackage&amp;quot;: &amp;quot;cn.xuexi.android&amp;quot;, &amp;quot;appActivity&amp;quot;: &amp;quot;com.alibaba.android.rimet.biz.home.activity.HomeActivity&amp;quot;}}\nDEBUG    urllib3.connectionpool:connectionpool.py:246 Starting new HTTP connection (1): 127.0.0.1:4723\nDEBUG    urllib3.util.retry:retry.py:596 Incremented Retry for (url=&amp;#x27;/wd/hub/session&amp;#x27;): Retry(total=2, connect=None, read=None, redirect=None, status=None)\nWARNING  urllib3.connectionpool:connectionpool.py:827 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by &amp;#x27;NewConnectionError(&amp;#x27;&amp;lt;urllib3.connection.HTTPConnection object at 0x000001BE6AA9D520&amp;gt;: Failed to establish a new connection: [WinError 10061] \u7531\u4e8e\u76ee\u6807\u8ba1\u7b97\u673a\u79ef\u6781\u62d2\u7edd\uff0c\u65e0\u6cd5\u8fde\u63a5\u3002&amp;#x27;)&amp;#x27;: /wd/hub/session\nDEBUG    urllib3.connectionpool:connectionpool.py:246 Starting new HTTP connection (2): 127.0.0.1:4723\nDEBUG    urllib3.util.retry:retry.py:596 Incremented Retry for (url=&amp;#x27;/wd/hub/session&amp;#x27;): Retry(total=1, connect=None, read=None, redirect=None, status=None)\nWARNING  urllib3.connectionpool:connectionpool.py:827 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by &amp;#x27;NewConnectionError(&amp;#x27;&amp;lt;urllib3.connection.HTTPConnection object at 0x000001BE6AA9D940&amp;gt;: Failed to establish a new connection: [WinError 10061] \u7531\u4e8e\u76ee\u6807\u8ba1\u7b97\u673a\u79ef\u6781\u62d2\u7edd\uff0c\u65e0\u6cd5\u8fde\u63a5\u3002&amp;#x27;)&amp;#x27;: /wd/hub/session\nDEBUG    urllib3.connectionpool:connectionpool.py:246 Starting new HTTP connection (3): 127.0.0.1:4723\nDEBUG    urllib3.util.retry:retry.py:596 Incremented Retry for (url=&amp;#x27;/wd/hub/session&amp;#x27;): Retry(total=0, connect=None, read=None, redirect=None, status=None)\nWARNING  urllib3.connectionpool:connectionpool.py:827 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by &amp;#x27;NewConnectionError(&amp;#x27;&amp;lt;urllib3.connection.HTTPConnection object at 0x000001BE6AAB9190&amp;gt;: Failed to establish a new connection: [WinError 10061] \u7531\u4e8e\u76ee\u6807\u8ba1\u7b97\u673a\u79ef\u6781\u62d2\u7edd\uff0c\u65e0\u6cd5\u8fde\u63a5\u3002&amp;#x27;)&amp;#x27;: /wd/hub/session\nDEBUG    urllib3.connectionpool:connectionpool.py:246 Starting new HTTP connection (4): 127.0.0.1:4723\n&#34;}], &#34;case/test_sousuo.py::TestSouSuo::test_01&#34;: [{&#34;extras&#34;: [], &#34;result&#34;: &#34;Error&#34;, &#34;testId&#34;: &#34;case/test_sousuo.py::TestSouSuo::test_01::setup&#34;, &#34;duration&#34;: &#34;00:00:08&#34;, &#34;resultsTableRow&#34;: [&#34;&lt;td class=\&#34;col-result\&#34;&gt;Error&lt;/td&gt;&#34;, &#34;&lt;td class=\&#34;col-testId\&#34;&gt;case/test_sousuo.py::TestSouSuo::test_01::setup&lt;/td&gt;&#34;, &#34;&lt;td class=\&#34;col-duration\&#34;&gt;00:00:08&lt;/td&gt;&#34;, &#34;&lt;td class=\&#34;col-links\&#34;&gt;&lt;/td&gt;&#34;], &#34;log&#34;: &#34;self = &amp;lt;urllib3.connection.HTTPConnection object at 0x000001BE6B899D30&amp;gt;\n\n    def _new_conn(self):\n        &amp;quot;&amp;quot;&amp;quot;Establish a socket connection and set nodelay settings on it.\n    \n        :return: New socket connection.\n        &amp;quot;&amp;quot;&amp;quot;\n        extra_kw = {}\n        if self.source_address:\n            extra_kw[&amp;quot;source_address&amp;quot;] = self.source_address\n    \n        if self.socket_options:\n            extra_kw[&amp;quot;socket_options&amp;quot;] = self.socket_options\n    \n        try:\n&amp;gt;           conn = connection.create_connection(\n                (self._dns_host, self.port), self.timeout, **extra_kw\n            )\n\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\connection.py:174: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\util\\connection.py:95: in create_connection\n    raise err\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _\n\naddress = (&amp;#x27;127.0.0.1&amp;#x27;, 4723), timeout = None, source_address = None\nsocket_options = [(6, 1, 1)]\n\n    def create_connection(\n        address,\n        timeout=socket._GLOBAL_DEFAULT_TIMEOUT,\n        source_address=None,\n        socket_options=None,\n    ):\n        &amp;quot;&amp;quot;&amp;quot;Connect to *address* and return the socket object.\n    \n        Convenience function.  Connect to *address* (a 2-tuple ``(host,\n        port)``) and return the socket object.  Passing the optional\n        *timeout* parameter will set the timeout on the socket instance\n        before attempting to connect.  If no *timeout* is supplied, the\n        global default timeout setting returned by :func:`socket.getdefaulttimeout`\n        is used.  If *source_address* is set it must be a tuple of (host, port)\n        for the socket to bind as a source address before making the connection.\n        An host of &amp;#x27;&amp;#x27; or port 0 tells the OS to use the default.\n        &amp;quot;&amp;quot;&amp;quot;\n    \n        host, port = address\n        if host.startswith(&amp;quot;[&amp;quot;):\n            host = host.strip(&amp;quot;[]&amp;quot;)\n        err = None\n    \n        # Using the value from allowed_gai_family() in the context of getaddrinfo lets\n        # us select whether to work with IPv4 DNS records, IPv6 records, or both.\n        # The original create_connection function always returns all records.\n        family = allowed_gai_family()\n    \n        try:\n            host.encode(&amp;quot;idna&amp;quot;)\n        except UnicodeError:\n            return six.raise_from(\n                LocationParseError(u&amp;quot;&amp;#x27;%s&amp;#x27;, label empty or too long&amp;quot; % host), None\n            )\n    \n        for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):\n            af, socktype, proto, canonname, sa = res\n            sock = None\n            try:\n                sock = socket.socket(af, socktype, proto)\n    \n                # If provided, set socket level options before connecting.\n                _set_socket_options(sock, socket_options)\n    \n                if timeout is not socket._GLOBAL_DEFAULT_TIMEOUT:\n                    sock.settimeout(timeout)\n                if source_address:\n                    sock.bind(source_address)\n&amp;gt;               sock.connect(sa)\nE               ConnectionRefusedError: [WinError 10061] \u7531\u4e8e\u76ee\u6807\u8ba1\u7b97\u673a\u79ef\u6781\u62d2\u7edd\uff0c\u65e0\u6cd5\u8fde\u63a5\u3002\n\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\util\\connection.py:85: ConnectionRefusedError\n\nDuring handling of the above exception, another exception occurred:\n\nself = &amp;lt;urllib3.connectionpool.HTTPConnectionPool object at 0x000001BE6B97FD00&amp;gt;\nmethod = &amp;#x27;POST&amp;#x27;, url = &amp;#x27;/wd/hub/session&amp;#x27;\nbody = &amp;#x27;{&amp;quot;capabilities&amp;quot;: {&amp;quot;alwaysMatch&amp;quot;: {&amp;quot;platformName&amp;quot;: &amp;quot;Android&amp;quot;, &amp;quot;appium:deviceName&amp;quot;: &amp;quot;emulator-5554&amp;quot;, &amp;quot;appium:noReset&amp;quot;: ...&amp;quot;: true, &amp;quot;appPackage&amp;quot;: &amp;quot;cn.xuexi.android&amp;quot;, &amp;quot;appActivity&amp;quot;: &amp;quot;com.alibaba.android.rimet.biz.home.activity.HomeActivity&amp;quot;}}&amp;#x27;\nheaders = {&amp;#x27;Accept&amp;#x27;: &amp;#x27;application/json&amp;#x27;, &amp;#x27;Connection&amp;#x27;: &amp;#x27;keep-alive&amp;#x27;, &amp;#x27;Content-Type&amp;#x27;: &amp;#x27;application/json;charset=UTF-8&amp;#x27;, &amp;#x27;User-Agent&amp;#x27;: &amp;#x27;appium/python 2.0.0 (selenium/4.0.0 (python windows))&amp;#x27;, ...}\nretries = Retry(total=0, connect=None, read=None, redirect=None, status=None)\nredirect = False, assert_same_host = False\ntimeout = &amp;lt;object object at 0x000001BE6A35BEB0&amp;gt;, pool_timeout = None\nrelease_conn = True, chunked = False, body_pos = None\nresponse_kw = {&amp;#x27;request_url&amp;#x27;: &amp;#x27;http://127.0.0.1:4723/wd/hub/session&amp;#x27;}\nparsed_url = Url(scheme=None, auth=None, host=None, port=None, path=&amp;#x27;/wd/hub/session&amp;#x27;, query=None, fragment=None)\ndestination_scheme = None, conn = None, release_this_conn = True\nhttp_tunnel_required = False, err = None, clean_exit = False\n\n    def urlopen(\n        self,\n        method,\n        url,\n        body=None,\n        headers=None,\n        retries=None,\n        redirect=True,\n        assert_same_host=True,\n        timeout=_Default,\n        pool_timeout=None,\n        release_conn=None,\n        chunked=False,\n        body_pos=None,\n        **response_kw\n    ):\n        &amp;quot;&amp;quot;&amp;quot;\n        Get a connection from the pool and perform an HTTP request. This is the\n        lowest level call for making a request, so you&amp;#x27;ll need to specify all\n        the raw details.\n    \n        .. note::\n    \n           More commonly, it&amp;#x27;s appropriate to use a convenience method provided\n           by :class:`.RequestMethods`, such as :meth:`request`.\n    \n        .. note::\n    \n           `release_conn` will only behave as expected if\n           `preload_content=False` because we want to make\n           `preload_content=False` the default behaviour someday soon without\n           breaking backwards compatibility.\n    \n        :param method:\n            HTTP request method (such as GET, POST, PUT, etc.)\n    \n        :param url:\n            The URL to perform the request on.\n    \n        :param body:\n            Data to send in the request body, either :class:`str`, :class:`bytes`,\n            an iterable of :class:`str`/:class:`bytes`, or a file-like object.\n    \n        :param headers:\n            Dictionary of custom headers to send, such as User-Agent,\n            If-None-Match, etc. If None, pool headers are used. If provided,\n            these headers completely replace any pool-specific headers.\n    \n        :param retries:\n            Configure the number of retries to allow before raising a\n            :class:`~urllib3.exceptions.MaxRetryError` exception.\n    \n            Pass ``None`` to retry until you receive a response. Pass a\n            :class:`~urllib3.util.retry.Retry` object for fine-grained control\n            over different types of retries.\n            Pass an integer number to retry connection errors that many times,\n            but no other types of errors. Pass zero to never retry.\n    \n            If ``False``, then retries are disabled and any exception is raised\n            immediately. Also, instead of raising a MaxRetryError on redirects,\n            the redirect response will be returned.\n    \n        :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.\n    \n        :param redirect:\n            If True, automatically handle redirects (status codes 301, 302,\n            303, 307, 308). Each redirect counts as a retry. Disabling retries\n            will disable redirect, too.\n    \n        :param assert_same_host:\n            If ``True``, will make sure that the host of the pool requests is\n            consistent else will raise HostChangedError. When ``False``, you can\n            use the pool on an HTTP proxy and request foreign hosts.\n    \n        :param timeout:\n            If specified, overrides the default timeout for this one\n            request. It may be a float (in seconds) or an instance of\n            :class:`urllib3.util.Timeout`.\n    \n        :param pool_timeout:\n            If set and the pool is set to block=True, then this method will\n            block for ``pool_timeout`` seconds and raise EmptyPoolError if no\n            connection is available within the time period.\n    \n        :param release_conn:\n            If False, then the urlopen call will not release the connection\n            back into the pool once a response is received (but will release if\n            you read the entire contents of the response such as when\n            `preload_content=True`). This is useful if you&amp;#x27;re not preloading\n            the response&amp;#x27;s content immediately. You will need to call\n            ``r.release_conn()`` on the response ``r`` to return the connection\n            back into the pool. If None, it takes the value of\n            ``response_kw.get(&amp;#x27;preload_content&amp;#x27;, True)``.\n    \n        :param chunked:\n            If True, urllib3 will send the body using chunked transfer\n            encoding. Otherwise, urllib3 will send the body using the standard\n            content-length form. Defaults to False.\n    \n        :param int body_pos:\n            Position to seek to in file-like body in the event of a retry or\n            redirect. Typically this won&amp;#x27;t need to be set because urllib3 will\n            auto-populate the value when needed.\n    \n        :param \\\\**response_kw:\n            Additional parameters are passed to\n            :meth:`urllib3.response.HTTPResponse.from_httplib`\n        &amp;quot;&amp;quot;&amp;quot;\n    \n        parsed_url = parse_url(url)\n        destination_scheme = parsed_url.scheme\n    \n        if headers is None:\n            headers = self.headers\n    \n        if not isinstance(retries, Retry):\n            retries = Retry.from_int(retries, redirect=redirect, default=self.retries)\n    \n        if release_conn is None:\n            release_conn = response_kw.get(&amp;quot;preload_content&amp;quot;, True)\n    \n        # Check host\n        if assert_same_host and not self.is_same_host(url):\n            raise HostChangedError(self, url, retries)\n    \n        # Ensure that the URL we&amp;#x27;re connecting to is properly encoded\n        if url.startswith(&amp;quot;/&amp;quot;):\n            url = six.ensure_str(_encode_target(url))\n        else:\n            url = six.ensure_str(parsed_url.url)\n    \n        conn = None\n    \n        # Track whether `conn` needs to be released before\n        # returning/raising/recursing. Update this variable if necessary, and\n        # leave `release_conn` constant throughout the function. That way, if\n        # the function recurses, the original value of `release_conn` will be\n        # passed down into the recursive call, and its value will be respected.\n        #\n        # See issue #651 [1] for details.\n        #\n        # [1] &amp;lt;https://github.com/urllib3/urllib3/issues/651&amp;gt;\n        release_this_conn = release_conn\n    \n        http_tunnel_required = connection_requires_http_tunnel(\n            self.proxy, self.proxy_config, destination_scheme\n        )\n    \n        # Merge the proxy headers. Only done when not using HTTP CONNECT. We\n        # have to copy the headers dict so we can safely change it without those\n        # changes being reflected in anyone else&amp;#x27;s copy.\n        if not http_tunnel_required:\n            headers = headers.copy()\n            headers.update(self.proxy_headers)\n    \n        # Must keep the exception bound to a separate variable or else Python 3\n        # complains about UnboundLocalError.\n        err = None\n    \n        # Keep track of whether we cleanly exited the except block. This\n        # ensures we do proper cleanup in finally.\n        clean_exit = False\n    \n        # Rewind body position, if needed. Record current position\n        # for future rewinds in the event of a redirect/retry.\n        body_pos = set_file_position(body, body_pos)\n    \n        try:\n            # Request a connection from the queue.\n            timeout_obj = self._get_timeout(timeout)\n            conn = self._get_conn(timeout=pool_timeout)\n    \n            conn.timeout = timeout_obj.connect_timeout\n    \n            is_new_proxy_conn = self.proxy is not None and not getattr(\n                conn, &amp;quot;sock&amp;quot;, None\n            )\n            if is_new_proxy_conn and http_tunnel_required:\n                self._prepare_proxy(conn)\n    \n            # Make the request on the httplib connection object.\n&amp;gt;           httplib_response = self._make_request(\n                conn,\n                method,\n                url,\n                timeout=timeout_obj,\n                body=body,\n                headers=headers,\n                chunked=chunked,\n            )\n\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\connectionpool.py:716: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\connectionpool.py:416: in _make_request\n    conn.request(method, url, **httplib_request_kw)\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\connection.py:244: in request\n    super(HTTPConnection, self).request(method, url, body=body, headers=headers)\nC:\\Program Files\\Python38\\lib\\http\\client.py:1230: in request\n    self._send_request(method, url, body, headers, encode_chunked)\nC:\\Program Files\\Python38\\lib\\http\\client.py:1276: in _send_request\n    self.endheaders(body, encode_chunked=encode_chunked)\nC:\\Program Files\\Python38\\lib\\http\\client.py:1225: in endheaders\n    self._send_output(message_body, encode_chunked=encode_chunked)\nC:\\Program Files\\Python38\\lib\\http\\client.py:1004: in _send_output\n    self.send(msg)\nC:\\Program Files\\Python38\\lib\\http\\client.py:944: in send\n    self.connect()\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\connection.py:205: in connect\n    conn = self._new_conn()\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _\n\nself = &amp;lt;urllib3.connection.HTTPConnection object at 0x000001BE6B899D30&amp;gt;\n\n    def _new_conn(self):\n        &amp;quot;&amp;quot;&amp;quot;Establish a socket connection and set nodelay settings on it.\n    \n        :return: New socket connection.\n        &amp;quot;&amp;quot;&amp;quot;\n        extra_kw = {}\n        if self.source_address:\n            extra_kw[&amp;quot;source_address&amp;quot;] = self.source_address\n    \n        if self.socket_options:\n            extra_kw[&amp;quot;socket_options&amp;quot;] = self.socket_options\n    \n        try:\n            conn = connection.create_connection(\n                (self._dns_host, self.port), self.timeout, **extra_kw\n            )\n    \n        except SocketTimeout:\n            raise ConnectTimeoutError(\n                self,\n                &amp;quot;Connection to %s timed out. (connect timeout=%s)&amp;quot;\n                % (self.host, self.timeout),\n            )\n    \n        except SocketError as e:\n&amp;gt;           raise NewConnectionError(\n                self, &amp;quot;Failed to establish a new connection: %s&amp;quot; % e\n            )\nE           urllib3.exceptions.NewConnectionError: &amp;lt;urllib3.connection.HTTPConnection object at 0x000001BE6B899D30&amp;gt;: Failed to establish a new connection: [WinError 10061] \u7531\u4e8e\u76ee\u6807\u8ba1\u7b97\u673a\u79ef\u6781\u62d2\u7edd\uff0c\u65e0\u6cd5\u8fde\u63a5\u3002\n\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\connection.py:186: NewConnectionError\n\nDuring handling of the above exception, another exception occurred:\n\nself = &amp;lt;test_sousuo.TestSouSuo object at 0x000001BE6AA697C0&amp;gt;\n\n    def setup_method(self):\n        logging.info(&amp;#x27;\u5b9e\u4f8b\u5316\u641c\u7d22\u9875\u9762\u7c7b&amp;#x27;)\n&amp;gt;       self.po=XueXiPage()\n\ncase\\test_sousuo.py:7: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _\nbase.py:18: in __init__\n    self.driver=webdriver.Remote(&amp;#x27;http://127.0.0.1:4723/wd/hub&amp;#x27;,cap)\nC:\\Program Files\\Python38\\lib\\site-packages\\appium\\webdriver\\webdriver.py:273: in __init__\n    super().__init__(\nC:\\Program Files\\Python38\\lib\\site-packages\\selenium\\webdriver\\remote\\webdriver.py:266: in __init__\n    self.start_session(capabilities, browser_profile)\nC:\\Program Files\\Python38\\lib\\site-packages\\appium\\webdriver\\webdriver.py:364: in start_session\n    response = self.execute(RemoteCommand.NEW_SESSION, parameters)\nC:\\Program Files\\Python38\\lib\\site-packages\\selenium\\webdriver\\remote\\webdriver.py:416: in execute\n    response = self.command_executor.execute(driver_command, params)\nC:\\Program Files\\Python38\\lib\\site-packages\\selenium\\webdriver\\remote\\remote_connection.py:398: in execute\n    return self._request(command_info[0], url, body=data)\nC:\\Program Files\\Python38\\lib\\site-packages\\selenium\\webdriver\\remote\\remote_connection.py:420: in _request\n    resp = self._conn.request(method, url, body=body, headers=headers)\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\request.py:81: in request\n    return self.request_encode_body(\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\request.py:173: in request_encode_body\n    return self.urlopen(method, url, **extra_kw)\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\poolmanager.py:376: in urlopen\n    response = conn.urlopen(method, u.request_uri, **kw)\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\connectionpool.py:830: in urlopen\n    return self.urlopen(\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\connectionpool.py:830: in urlopen\n    return self.urlopen(\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\connectionpool.py:830: in urlopen\n    return self.urlopen(\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\connectionpool.py:802: in urlopen\n    retries = retries.increment(\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _\n\nself = Retry(total=0, connect=None, read=None, redirect=None, status=None)\nmethod = &amp;#x27;POST&amp;#x27;, url = &amp;#x27;/wd/hub/session&amp;#x27;, response = None\nerror = NewConnectionError(&amp;#x27;&amp;lt;urllib3.connection.HTTPConnection object at 0x000001BE6B899D30&amp;gt;: Failed to establish a new connection: [WinError 10061] \u7531\u4e8e\u76ee\u6807\u8ba1\u7b97\u673a\u79ef\u6781\u62d2\u7edd\uff0c\u65e0\u6cd5\u8fde\u63a5\u3002&amp;#x27;)\n_pool = &amp;lt;urllib3.connectionpool.HTTPConnectionPool object at 0x000001BE6B97FD00&amp;gt;\n_stacktrace = &amp;lt;traceback object at 0x000001BE6B79F9C0&amp;gt;\n\n    def increment(\n        self,\n        method=None,\n        url=None,\n        response=None,\n        error=None,\n        _pool=None,\n        _stacktrace=None,\n    ):\n        &amp;quot;&amp;quot;&amp;quot;Return a new Retry object with incremented retry counters.\n    \n        :param response: A response object, or None, if the server did not\n            return a response.\n        :type response: :class:`~urllib3.response.HTTPResponse`\n        :param Exception error: An error encountered during the request, or\n            None if the response was received successfully.\n    \n        :return: A new ``Retry`` object.\n        &amp;quot;&amp;quot;&amp;quot;\n        if self.total is False and error:\n            # Disabled, indicate to re-raise the error.\n            raise six.reraise(type(error), error, _stacktrace)\n    \n        total = self.total\n        if total is not None:\n            total -= 1\n    \n        connect = self.connect\n        read = self.read\n        redirect = self.redirect\n        status_count = self.status\n        other = self.other\n        cause = &amp;quot;unknown&amp;quot;\n        status = None\n        redirect_location = None\n    \n        if error and self._is_connection_error(error):\n            # Connect retry?\n            if connect is False:\n                raise six.reraise(type(error), error, _stacktrace)\n            elif connect is not None:\n                connect -= 1\n    \n        elif error and self._is_read_error(error):\n            # Read retry?\n            if read is False or not self._is_method_retryable(method):\n                raise six.reraise(type(error), error, _stacktrace)\n            elif read is not None:\n                read -= 1\n    \n        elif error:\n            # Other retry?\n            if other is not None:\n                other -= 1\n    \n        elif response and response.get_redirect_location():\n            # Redirect retry?\n            if redirect is not None:\n                redirect -= 1\n            cause = &amp;quot;too many redirects&amp;quot;\n            redirect_location = response.get_redirect_location()\n            status = response.status\n    \n        else:\n            # Incrementing because of a server error like a 500 in\n            # status_forcelist and the given method is in the allowed_methods\n            cause = ResponseError.GENERIC_ERROR\n            if response and response.status:\n                if status_count is not None:\n                    status_count -= 1\n                cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)\n                status = response.status\n    \n        history = self.history + (\n            RequestHistory(method, url, error, status, redirect_location),\n        )\n    \n        new_retry = self.new(\n            total=total,\n            connect=connect,\n            read=read,\n            redirect=redirect,\n            status=status_count,\n            other=other,\n            history=history,\n        )\n    \n        if new_retry.is_exhausted():\n&amp;gt;           raise MaxRetryError(_pool, url, error or ResponseError(cause))\nE           urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host=&amp;#x27;127.0.0.1&amp;#x27;, port=4723): Max retries exceeded with url: /wd/hub/session (Caused by NewConnectionError(&amp;#x27;&amp;lt;urllib3.connection.HTTPConnection object at 0x000001BE6B899D30&amp;gt;: Failed to establish a new connection: [WinError 10061] \u7531\u4e8e\u76ee\u6807\u8ba1\u7b97\u673a\u79ef\u6781\u62d2\u7edd\uff0c\u65e0\u6cd5\u8fde\u63a5\u3002&amp;#x27;))\n\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\util\\retry.py:594: MaxRetryError\n\n------------------------------ Captured log setup ------------------------------\nINFO     root:test_sousuo.py:6 \u5b9e\u4f8b\u5316\u641c\u7d22\u9875\u9762\u7c7b\nDEBUG    selenium.webdriver.remote.remote_connection:remote_connection.py:412 POST http://127.0.0.1:4723/wd/hub/session {&amp;quot;capabilities&amp;quot;: {&amp;quot;alwaysMatch&amp;quot;: {&amp;quot;platformName&amp;quot;: &amp;quot;Android&amp;quot;, &amp;quot;appium:deviceName&amp;quot;: &amp;quot;emulator-5554&amp;quot;, &amp;quot;appium:noReset&amp;quot;: true, &amp;quot;appium:appPackage&amp;quot;: &amp;quot;cn.xuexi.android&amp;quot;, &amp;quot;appium:appActivity&amp;quot;: &amp;quot;com.alibaba.android.rimet.biz.home.activity.HomeActivity&amp;quot;}, &amp;quot;firstMatch&amp;quot;: [{}]}, &amp;quot;desiredCapabilities&amp;quot;: {&amp;quot;platformName&amp;quot;: &amp;quot;Android&amp;quot;, &amp;quot;deviceName&amp;quot;: &amp;quot;emulator-5554&amp;quot;, &amp;quot;noReset&amp;quot;: true, &amp;quot;appPackage&amp;quot;: &amp;quot;cn.xuexi.android&amp;quot;, &amp;quot;appActivity&amp;quot;: &amp;quot;com.alibaba.android.rimet.biz.home.activity.HomeActivity&amp;quot;}}\nDEBUG    urllib3.connectionpool:connectionpool.py:246 Starting new HTTP connection (1): 127.0.0.1:4723\nDEBUG    urllib3.util.retry:retry.py:596 Incremented Retry for (url=&amp;#x27;/wd/hub/session&amp;#x27;): Retry(total=2, connect=None, read=None, redirect=None, status=None)\nWARNING  urllib3.connectionpool:connectionpool.py:827 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by &amp;#x27;NewConnectionError(&amp;#x27;&amp;lt;urllib3.connection.HTTPConnection object at 0x000001BE6B97FF70&amp;gt;: Failed to establish a new connection: [WinError 10061] \u7531\u4e8e\u76ee\u6807\u8ba1\u7b97\u673a\u79ef\u6781\u62d2\u7edd\uff0c\u65e0\u6cd5\u8fde\u63a5\u3002&amp;#x27;)&amp;#x27;: /wd/hub/session\nDEBUG    urllib3.connectionpool:connectionpool.py:246 Starting new HTTP connection (2): 127.0.0.1:4723\nDEBUG    urllib3.util.retry:retry.py:596 Incremented Retry for (url=&amp;#x27;/wd/hub/session&amp;#x27;): Retry(total=1, connect=None, read=None, redirect=None, status=None)\nWARNING  urllib3.connectionpool:connectionpool.py:827 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by &amp;#x27;NewConnectionError(&amp;#x27;&amp;lt;urllib3.connection.HTTPConnection object at 0x000001BE6B97F9A0&amp;gt;: Failed to establish a new connection: [WinError 10061] \u7531\u4e8e\u76ee\u6807\u8ba1\u7b97\u673a\u79ef\u6781\u62d2\u7edd\uff0c\u65e0\u6cd5\u8fde\u63a5\u3002&amp;#x27;)&amp;#x27;: /wd/hub/session\nDEBUG    urllib3.connectionpool:connectionpool.py:246 Starting new HTTP connection (3): 127.0.0.1:4723\nDEBUG    urllib3.util.retry:retry.py:596 Incremented Retry for (url=&amp;#x27;/wd/hub/session&amp;#x27;): Retry(total=0, connect=None, read=None, redirect=None, status=None)\nWARNING  urllib3.connectionpool:connectionpool.py:827 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by &amp;#x27;NewConnectionError(&amp;#x27;&amp;lt;urllib3.connection.HTTPConnection object at 0x000001BE6B899DC0&amp;gt;: Failed to establish a new connection: [WinError 10061] \u7531\u4e8e\u76ee\u6807\u8ba1\u7b97\u673a\u79ef\u6781\u62d2\u7edd\uff0c\u65e0\u6cd5\u8fde\u63a5\u3002&amp;#x27;)&amp;#x27;: /wd/hub/session\nDEBUG    urllib3.connectionpool:connectionpool.py:246 Starting new HTTP connection (4): 127.0.0.1:4723\n&#34;}], &#34;case/test_yaowen.py::TestYaoWen::test_01&#34;: [{&#34;extras&#34;: [], &#34;result&#34;: &#34;Error&#34;, &#34;testId&#34;: &#34;case/test_yaowen.py::TestYaoWen::test_01::setup&#34;, &#34;duration&#34;: &#34;00:00:08&#34;, &#34;resultsTableRow&#34;: [&#34;&lt;td class=\&#34;col-result\&#34;&gt;Error&lt;/td&gt;&#34;, &#34;&lt;td class=\&#34;col-testId\&#34;&gt;case/test_yaowen.py::TestYaoWen::test_01::setup&lt;/td&gt;&#34;, &#34;&lt;td class=\&#34;col-duration\&#34;&gt;00:00:08&lt;/td&gt;&#34;, &#34;&lt;td class=\&#34;col-links\&#34;&gt;&lt;/td&gt;&#34;], &#34;log&#34;: &#34;self = &amp;lt;urllib3.connection.HTTPConnection object at 0x000001BE6B762910&amp;gt;\n\n    def _new_conn(self):\n        &amp;quot;&amp;quot;&amp;quot;Establish a socket connection and set nodelay settings on it.\n    \n        :return: New socket connection.\n        &amp;quot;&amp;quot;&amp;quot;\n        extra_kw = {}\n        if self.source_address:\n            extra_kw[&amp;quot;source_address&amp;quot;] = self.source_address\n    \n        if self.socket_options:\n            extra_kw[&amp;quot;socket_options&amp;quot;] = self.socket_options\n    \n        try:\n&amp;gt;           conn = connection.create_connection(\n                (self._dns_host, self.port), self.timeout, **extra_kw\n            )\n\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\connection.py:174: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\util\\connection.py:95: in create_connection\n    raise err\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _\n\naddress = (&amp;#x27;127.0.0.1&amp;#x27;, 4723), timeout = None, source_address = None\nsocket_options = [(6, 1, 1)]\n\n    def create_connection(\n        address,\n        timeout=socket._GLOBAL_DEFAULT_TIMEOUT,\n        source_address=None,\n        socket_options=None,\n    ):\n        &amp;quot;&amp;quot;&amp;quot;Connect to *address* and return the socket object.\n    \n        Convenience function.  Connect to *address* (a 2-tuple ``(host,\n        port)``) and return the socket object.  Passing the optional\n        *timeout* parameter will set the timeout on the socket instance\n        before attempting to connect.  If no *timeout* is supplied, the\n        global default timeout setting returned by :func:`socket.getdefaulttimeout`\n        is used.  If *source_address* is set it must be a tuple of (host, port)\n        for the socket to bind as a source address before making the connection.\n        An host of &amp;#x27;&amp;#x27; or port 0 tells the OS to use the default.\n        &amp;quot;&amp;quot;&amp;quot;\n    \n        host, port = address\n        if host.startswith(&amp;quot;[&amp;quot;):\n            host = host.strip(&amp;quot;[]&amp;quot;)\n        err = None\n    \n        # Using the value from allowed_gai_family() in the context of getaddrinfo lets\n        # us select whether to work with IPv4 DNS records, IPv6 records, or both.\n        # The original create_connection function always returns all records.\n        family = allowed_gai_family()\n    \n        try:\n            host.encode(&amp;quot;idna&amp;quot;)\n        except UnicodeError:\n            return six.raise_from(\n                LocationParseError(u&amp;quot;&amp;#x27;%s&amp;#x27;, label empty or too long&amp;quot; % host), None\n            )\n    \n        for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):\n            af, socktype, proto, canonname, sa = res\n            sock = None\n            try:\n                sock = socket.socket(af, socktype, proto)\n    \n                # If provided, set socket level options before connecting.\n                _set_socket_options(sock, socket_options)\n    \n                if timeout is not socket._GLOBAL_DEFAULT_TIMEOUT:\n                    sock.settimeout(timeout)\n                if source_address:\n                    sock.bind(source_address)\n&amp;gt;               sock.connect(sa)\nE               ConnectionRefusedError: [WinError 10061] \u7531\u4e8e\u76ee\u6807\u8ba1\u7b97\u673a\u79ef\u6781\u62d2\u7edd\uff0c\u65e0\u6cd5\u8fde\u63a5\u3002\n\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\util\\connection.py:85: ConnectionRefusedError\n\nDuring handling of the above exception, another exception occurred:\n\nself = &amp;lt;urllib3.connectionpool.HTTPConnectionPool object at 0x000001BE6B7B1220&amp;gt;\nmethod = &amp;#x27;POST&amp;#x27;, url = &amp;#x27;/wd/hub/session&amp;#x27;\nbody = &amp;#x27;{&amp;quot;capabilities&amp;quot;: {&amp;quot;alwaysMatch&amp;quot;: {&amp;quot;platformName&amp;quot;: &amp;quot;Android&amp;quot;, &amp;quot;appium:deviceName&amp;quot;: &amp;quot;emulator-5554&amp;quot;, &amp;quot;appium:noReset&amp;quot;: ...&amp;quot;: true, &amp;quot;appPackage&amp;quot;: &amp;quot;cn.xuexi.android&amp;quot;, &amp;quot;appActivity&amp;quot;: &amp;quot;com.alibaba.android.rimet.biz.home.activity.HomeActivity&amp;quot;}}&amp;#x27;\nheaders = {&amp;#x27;Accept&amp;#x27;: &amp;#x27;application/json&amp;#x27;, &amp;#x27;Connection&amp;#x27;: &amp;#x27;keep-alive&amp;#x27;, &amp;#x27;Content-Type&amp;#x27;: &amp;#x27;application/json;charset=UTF-8&amp;#x27;, &amp;#x27;User-Agent&amp;#x27;: &amp;#x27;appium/python 2.0.0 (selenium/4.0.0 (python windows))&amp;#x27;, ...}\nretries = Retry(total=0, connect=None, read=None, redirect=None, status=None)\nredirect = False, assert_same_host = False\ntimeout = &amp;lt;object object at 0x000001BE6A35BEB0&amp;gt;, pool_timeout = None\nrelease_conn = True, chunked = False, body_pos = None\nresponse_kw = {&amp;#x27;request_url&amp;#x27;: &amp;#x27;http://127.0.0.1:4723/wd/hub/session&amp;#x27;}\nparsed_url = Url(scheme=None, auth=None, host=None, port=None, path=&amp;#x27;/wd/hub/session&amp;#x27;, query=None, fragment=None)\ndestination_scheme = None, conn = None, release_this_conn = True\nhttp_tunnel_required = False, err = None, clean_exit = False\n\n    def urlopen(\n        self,\n        method,\n        url,\n        body=None,\n        headers=None,\n        retries=None,\n        redirect=True,\n        assert_same_host=True,\n        timeout=_Default,\n        pool_timeout=None,\n        release_conn=None,\n        chunked=False,\n        body_pos=None,\n        **response_kw\n    ):\n        &amp;quot;&amp;quot;&amp;quot;\n        Get a connection from the pool and perform an HTTP request. This is the\n        lowest level call for making a request, so you&amp;#x27;ll need to specify all\n        the raw details.\n    \n        .. note::\n    \n           More commonly, it&amp;#x27;s appropriate to use a convenience method provided\n           by :class:`.RequestMethods`, such as :meth:`request`.\n    \n        .. note::\n    \n           `release_conn` will only behave as expected if\n           `preload_content=False` because we want to make\n           `preload_content=False` the default behaviour someday soon without\n           breaking backwards compatibility.\n    \n        :param method:\n            HTTP request method (such as GET, POST, PUT, etc.)\n    \n        :param url:\n            The URL to perform the request on.\n    \n        :param body:\n            Data to send in the request body, either :class:`str`, :class:`bytes`,\n            an iterable of :class:`str`/:class:`bytes`, or a file-like object.\n    \n        :param headers:\n            Dictionary of custom headers to send, such as User-Agent,\n            If-None-Match, etc. If None, pool headers are used. If provided,\n            these headers completely replace any pool-specific headers.\n    \n        :param retries:\n            Configure the number of retries to allow before raising a\n            :class:`~urllib3.exceptions.MaxRetryError` exception.\n    \n            Pass ``None`` to retry until you receive a response. Pass a\n            :class:`~urllib3.util.retry.Retry` object for fine-grained control\n            over different types of retries.\n            Pass an integer number to retry connection errors that many times,\n            but no other types of errors. Pass zero to never retry.\n    \n            If ``False``, then retries are disabled and any exception is raised\n            immediately. Also, instead of raising a MaxRetryError on redirects,\n            the redirect response will be returned.\n    \n        :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int.\n    \n        :param redirect:\n            If True, automatically handle redirects (status codes 301, 302,\n            303, 307, 308). Each redirect counts as a retry. Disabling retries\n            will disable redirect, too.\n    \n        :param assert_same_host:\n            If ``True``, will make sure that the host of the pool requests is\n            consistent else will raise HostChangedError. When ``False``, you can\n            use the pool on an HTTP proxy and request foreign hosts.\n    \n        :param timeout:\n            If specified, overrides the default timeout for this one\n            request. It may be a float (in seconds) or an instance of\n            :class:`urllib3.util.Timeout`.\n    \n        :param pool_timeout:\n            If set and the pool is set to block=True, then this method will\n            block for ``pool_timeout`` seconds and raise EmptyPoolError if no\n            connection is available within the time period.\n    \n        :param release_conn:\n            If False, then the urlopen call will not release the connection\n            back into the pool once a response is received (but will release if\n            you read the entire contents of the response such as when\n            `preload_content=True`). This is useful if you&amp;#x27;re not preloading\n            the response&amp;#x27;s content immediately. You will need to call\n            ``r.release_conn()`` on the response ``r`` to return the connection\n            back into the pool. If None, it takes the value of\n            ``response_kw.get(&amp;#x27;preload_content&amp;#x27;, True)``.\n    \n        :param chunked:\n            If True, urllib3 will send the body using chunked transfer\n            encoding. Otherwise, urllib3 will send the body using the standard\n            content-length form. Defaults to False.\n    \n        :param int body_pos:\n            Position to seek to in file-like body in the event of a retry or\n            redirect. Typically this won&amp;#x27;t need to be set because urllib3 will\n            auto-populate the value when needed.\n    \n        :param \\\\**response_kw:\n            Additional parameters are passed to\n            :meth:`urllib3.response.HTTPResponse.from_httplib`\n        &amp;quot;&amp;quot;&amp;quot;\n    \n        parsed_url = parse_url(url)\n        destination_scheme = parsed_url.scheme\n    \n        if headers is None:\n            headers = self.headers\n    \n        if not isinstance(retries, Retry):\n            retries = Retry.from_int(retries, redirect=redirect, default=self.retries)\n    \n        if release_conn is None:\n            release_conn = response_kw.get(&amp;quot;preload_content&amp;quot;, True)\n    \n        # Check host\n        if assert_same_host and not self.is_same_host(url):\n            raise HostChangedError(self, url, retries)\n    \n        # Ensure that the URL we&amp;#x27;re connecting to is properly encoded\n        if url.startswith(&amp;quot;/&amp;quot;):\n            url = six.ensure_str(_encode_target(url))\n        else:\n            url = six.ensure_str(parsed_url.url)\n    \n        conn = None\n    \n        # Track whether `conn` needs to be released before\n        # returning/raising/recursing. Update this variable if necessary, and\n        # leave `release_conn` constant throughout the function. That way, if\n        # the function recurses, the original value of `release_conn` will be\n        # passed down into the recursive call, and its value will be respected.\n        #\n        # See issue #651 [1] for details.\n        #\n        # [1] &amp;lt;https://github.com/urllib3/urllib3/issues/651&amp;gt;\n        release_this_conn = release_conn\n    \n        http_tunnel_required = connection_requires_http_tunnel(\n            self.proxy, self.proxy_config, destination_scheme\n        )\n    \n        # Merge the proxy headers. Only done when not using HTTP CONNECT. We\n        # have to copy the headers dict so we can safely change it without those\n        # changes being reflected in anyone else&amp;#x27;s copy.\n        if not http_tunnel_required:\n            headers = headers.copy()\n            headers.update(self.proxy_headers)\n    \n        # Must keep the exception bound to a separate variable or else Python 3\n        # complains about UnboundLocalError.\n        err = None\n    \n        # Keep track of whether we cleanly exited the except block. This\n        # ensures we do proper cleanup in finally.\n        clean_exit = False\n    \n        # Rewind body position, if needed. Record current position\n        # for future rewinds in the event of a redirect/retry.\n        body_pos = set_file_position(body, body_pos)\n    \n        try:\n            # Request a connection from the queue.\n            timeout_obj = self._get_timeout(timeout)\n            conn = self._get_conn(timeout=pool_timeout)\n    \n            conn.timeout = timeout_obj.connect_timeout\n    \n            is_new_proxy_conn = self.proxy is not None and not getattr(\n                conn, &amp;quot;sock&amp;quot;, None\n            )\n            if is_new_proxy_conn and http_tunnel_required:\n                self._prepare_proxy(conn)\n    \n            # Make the request on the httplib connection object.\n&amp;gt;           httplib_response = self._make_request(\n                conn,\n                method,\n                url,\n                timeout=timeout_obj,\n                body=body,\n                headers=headers,\n                chunked=chunked,\n            )\n\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\connectionpool.py:716: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\connectionpool.py:416: in _make_request\n    conn.request(method, url, **httplib_request_kw)\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\connection.py:244: in request\n    super(HTTPConnection, self).request(method, url, body=body, headers=headers)\nC:\\Program Files\\Python38\\lib\\http\\client.py:1230: in request\n    self._send_request(method, url, body, headers, encode_chunked)\nC:\\Program Files\\Python38\\lib\\http\\client.py:1276: in _send_request\n    self.endheaders(body, encode_chunked=encode_chunked)\nC:\\Program Files\\Python38\\lib\\http\\client.py:1225: in endheaders\n    self._send_output(message_body, encode_chunked=encode_chunked)\nC:\\Program Files\\Python38\\lib\\http\\client.py:1004: in _send_output\n    self.send(msg)\nC:\\Program Files\\Python38\\lib\\http\\client.py:944: in send\n    self.connect()\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\connection.py:205: in connect\n    conn = self._new_conn()\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _\n\nself = &amp;lt;urllib3.connection.HTTPConnection object at 0x000001BE6B762910&amp;gt;\n\n    def _new_conn(self):\n        &amp;quot;&amp;quot;&amp;quot;Establish a socket connection and set nodelay settings on it.\n    \n        :return: New socket connection.\n        &amp;quot;&amp;quot;&amp;quot;\n        extra_kw = {}\n        if self.source_address:\n            extra_kw[&amp;quot;source_address&amp;quot;] = self.source_address\n    \n        if self.socket_options:\n            extra_kw[&amp;quot;socket_options&amp;quot;] = self.socket_options\n    \n        try:\n            conn = connection.create_connection(\n                (self._dns_host, self.port), self.timeout, **extra_kw\n            )\n    \n        except SocketTimeout:\n            raise ConnectTimeoutError(\n                self,\n                &amp;quot;Connection to %s timed out. (connect timeout=%s)&amp;quot;\n                % (self.host, self.timeout),\n            )\n    \n        except SocketError as e:\n&amp;gt;           raise NewConnectionError(\n                self, &amp;quot;Failed to establish a new connection: %s&amp;quot; % e\n            )\nE           urllib3.exceptions.NewConnectionError: &amp;lt;urllib3.connection.HTTPConnection object at 0x000001BE6B762910&amp;gt;: Failed to establish a new connection: [WinError 10061] \u7531\u4e8e\u76ee\u6807\u8ba1\u7b97\u673a\u79ef\u6781\u62d2\u7edd\uff0c\u65e0\u6cd5\u8fde\u63a5\u3002\n\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\connection.py:186: NewConnectionError\n\nDuring handling of the above exception, another exception occurred:\n\nself = &amp;lt;test_yaowen.TestYaoWen object at 0x000001BE6AA69CA0&amp;gt;\n\n    def setup_method(self):\n        logging.info(&amp;#x27;\u5b9e\u4f8b\u5316\u641c\u7d22\u9875\u9762\u7c7b&amp;#x27;)\n&amp;gt;       self.po=XueXiPage()\n\ncase\\test_yaowen.py:7: \n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _\nbase.py:18: in __init__\n    self.driver=webdriver.Remote(&amp;#x27;http://127.0.0.1:4723/wd/hub&amp;#x27;,cap)\nC:\\Program Files\\Python38\\lib\\site-packages\\appium\\webdriver\\webdriver.py:273: in __init__\n    super().__init__(\nC:\\Program Files\\Python38\\lib\\site-packages\\selenium\\webdriver\\remote\\webdriver.py:266: in __init__\n    self.start_session(capabilities, browser_profile)\nC:\\Program Files\\Python38\\lib\\site-packages\\appium\\webdriver\\webdriver.py:364: in start_session\n    response = self.execute(RemoteCommand.NEW_SESSION, parameters)\nC:\\Program Files\\Python38\\lib\\site-packages\\selenium\\webdriver\\remote\\webdriver.py:416: in execute\n    response = self.command_executor.execute(driver_command, params)\nC:\\Program Files\\Python38\\lib\\site-packages\\selenium\\webdriver\\remote\\remote_connection.py:398: in execute\n    return self._request(command_info[0], url, body=data)\nC:\\Program Files\\Python38\\lib\\site-packages\\selenium\\webdriver\\remote\\remote_connection.py:420: in _request\n    resp = self._conn.request(method, url, body=body, headers=headers)\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\request.py:81: in request\n    return self.request_encode_body(\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\request.py:173: in request_encode_body\n    return self.urlopen(method, url, **extra_kw)\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\poolmanager.py:376: in urlopen\n    response = conn.urlopen(method, u.request_uri, **kw)\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\connectionpool.py:830: in urlopen\n    return self.urlopen(\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\connectionpool.py:830: in urlopen\n    return self.urlopen(\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\connectionpool.py:830: in urlopen\n    return self.urlopen(\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\connectionpool.py:802: in urlopen\n    retries = retries.increment(\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _\n\nself = Retry(total=0, connect=None, read=None, redirect=None, status=None)\nmethod = &amp;#x27;POST&amp;#x27;, url = &amp;#x27;/wd/hub/session&amp;#x27;, response = None\nerror = NewConnectionError(&amp;#x27;&amp;lt;urllib3.connection.HTTPConnection object at 0x000001BE6B762910&amp;gt;: Failed to establish a new connection: [WinError 10061] \u7531\u4e8e\u76ee\u6807\u8ba1\u7b97\u673a\u79ef\u6781\u62d2\u7edd\uff0c\u65e0\u6cd5\u8fde\u63a5\u3002&amp;#x27;)\n_pool = &amp;lt;urllib3.connectionpool.HTTPConnectionPool object at 0x000001BE6B7B1220&amp;gt;\n_stacktrace = &amp;lt;traceback object at 0x000001BE6AADAD80&amp;gt;\n\n    def increment(\n        self,\n        method=None,\n        url=None,\n        response=None,\n        error=None,\n        _pool=None,\n        _stacktrace=None,\n    ):\n        &amp;quot;&amp;quot;&amp;quot;Return a new Retry object with incremented retry counters.\n    \n        :param response: A response object, or None, if the server did not\n            return a response.\n        :type response: :class:`~urllib3.response.HTTPResponse`\n        :param Exception error: An error encountered during the request, or\n            None if the response was received successfully.\n    \n        :return: A new ``Retry`` object.\n        &amp;quot;&amp;quot;&amp;quot;\n        if self.total is False and error:\n            # Disabled, indicate to re-raise the error.\n            raise six.reraise(type(error), error, _stacktrace)\n    \n        total = self.total\n        if total is not None:\n            total -= 1\n    \n        connect = self.connect\n        read = self.read\n        redirect = self.redirect\n        status_count = self.status\n        other = self.other\n        cause = &amp;quot;unknown&amp;quot;\n        status = None\n        redirect_location = None\n    \n        if error and self._is_connection_error(error):\n            # Connect retry?\n            if connect is False:\n                raise six.reraise(type(error), error, _stacktrace)\n            elif connect is not None:\n                connect -= 1\n    \n        elif error and self._is_read_error(error):\n            # Read retry?\n            if read is False or not self._is_method_retryable(method):\n                raise six.reraise(type(error), error, _stacktrace)\n            elif read is not None:\n                read -= 1\n    \n        elif error:\n            # Other retry?\n            if other is not None:\n                other -= 1\n    \n        elif response and response.get_redirect_location():\n            # Redirect retry?\n            if redirect is not None:\n                redirect -= 1\n            cause = &amp;quot;too many redirects&amp;quot;\n            redirect_location = response.get_redirect_location()\n            status = response.status\n    \n        else:\n            # Incrementing because of a server error like a 500 in\n            # status_forcelist and the given method is in the allowed_methods\n            cause = ResponseError.GENERIC_ERROR\n            if response and response.status:\n                if status_count is not None:\n                    status_count -= 1\n                cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)\n                status = response.status\n    \n        history = self.history + (\n            RequestHistory(method, url, error, status, redirect_location),\n        )\n    \n        new_retry = self.new(\n            total=total,\n            connect=connect,\n            read=read,\n            redirect=redirect,\n            status=status_count,\n            other=other,\n            history=history,\n        )\n    \n        if new_retry.is_exhausted():\n&amp;gt;           raise MaxRetryError(_pool, url, error or ResponseError(cause))\nE           urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host=&amp;#x27;127.0.0.1&amp;#x27;, port=4723): Max retries exceeded with url: /wd/hub/session (Caused by NewConnectionError(&amp;#x27;&amp;lt;urllib3.connection.HTTPConnection object at 0x000001BE6B762910&amp;gt;: Failed to establish a new connection: [WinError 10061] \u7531\u4e8e\u76ee\u6807\u8ba1\u7b97\u673a\u79ef\u6781\u62d2\u7edd\uff0c\u65e0\u6cd5\u8fde\u63a5\u3002&amp;#x27;))\n\nC:\\Program Files\\Python38\\lib\\site-packages\\urllib3\\util\\retry.py:594: MaxRetryError\n\n------------------------------ Captured log setup ------------------------------\nINFO     root:test_yaowen.py:6 \u5b9e\u4f8b\u5316\u641c\u7d22\u9875\u9762\u7c7b\nDEBUG    selenium.webdriver.remote.remote_connection:remote_connection.py:412 POST http://127.0.0.1:4723/wd/hub/session {&amp;quot;capabilities&amp;quot;: {&amp;quot;alwaysMatch&amp;quot;: {&amp;quot;platformName&amp;quot;: &amp;quot;Android&amp;quot;, &amp;quot;appium:deviceName&amp;quot;: &amp;quot;emulator-5554&amp;quot;, &amp;quot;appium:noReset&amp;quot;: true, &amp;quot;appium:appPackage&amp;quot;: &amp;quot;cn.xuexi.android&amp;quot;, &amp;quot;appium:appActivity&amp;quot;: &amp;quot;com.alibaba.android.rimet.biz.home.activity.HomeActivity&amp;quot;}, &amp;quot;firstMatch&amp;quot;: [{}]}, &amp;quot;desiredCapabilities&amp;quot;: {&amp;quot;platformName&amp;quot;: &amp;quot;Android&amp;quot;, &amp;quot;deviceName&amp;quot;: &amp;quot;emulator-5554&amp;quot;, &amp;quot;noReset&amp;quot;: true, &amp;quot;appPackage&amp;quot;: &amp;quot;cn.xuexi.android&amp;quot;, &amp;quot;appActivity&amp;quot;: &amp;quot;com.alibaba.android.rimet.biz.home.activity.HomeActivity&amp;quot;}}\nDEBUG    urllib3.connectionpool:connectionpool.py:246 Starting new HTTP connection (1): 127.0.0.1:4723\nDEBUG    urllib3.util.retry:retry.py:596 Incremented Retry for (url=&amp;#x27;/wd/hub/session&amp;#x27;): Retry(total=2, connect=None, read=None, redirect=None, status=None)\nWARNING  urllib3.connectionpool:connectionpool.py:827 Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by &amp;#x27;NewConnectionError(&amp;#x27;&amp;lt;urllib3.connection.HTTPConnection object at 0x000001BE6AA696A0&amp;gt;: Failed to establish a new connection: [WinError 10061] \u7531\u4e8e\u76ee\u6807\u8ba1\u7b97\u673a\u79ef\u6781\u62d2\u7edd\uff0c\u65e0\u6cd5\u8fde\u63a5\u3002&amp;#x27;)&amp;#x27;: /wd/hub/session\nDEBUG    urllib3.connectionpool:connectionpool.py:246 Starting new HTTP connection (2): 127.0.0.1:4723\nDEBUG    urllib3.util.retry:retry.py:596 Incremented Retry for (url=&amp;#x27;/wd/hub/session&amp;#x27;): Retry(total=1, connect=None, read=None, redirect=None, status=None)\nWARNING  urllib3.connectionpool:connectionpool.py:827 Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by &amp;#x27;NewConnectionError(&amp;#x27;&amp;lt;urllib3.connection.HTTPConnection object at 0x000001BE6AA699D0&amp;gt;: Failed to establish a new connection: [WinError 10061] \u7531\u4e8e\u76ee\u6807\u8ba1\u7b97\u673a\u79ef\u6781\u62d2\u7edd\uff0c\u65e0\u6cd5\u8fde\u63a5\u3002&amp;#x27;)&amp;#x27;: /wd/hub/session\nDEBUG    urllib3.connectionpool:connectionpool.py:246 Starting new HTTP connection (3): 127.0.0.1:4723\nDEBUG    urllib3.util.retry:retry.py:596 Incremented Retry for (url=&amp;#x27;/wd/hub/session&amp;#x27;): Retry(total=0, connect=None, read=None, redirect=None, status=None)\nWARNING  urllib3.connectionpool:connectionpool.py:827 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by &amp;#x27;NewConnectionError(&amp;#x27;&amp;lt;urllib3.connection.HTTPConnection object at 0x000001BE6AA69E50&amp;gt;: Failed to establish a new connection: [WinError 10061] \u7531\u4e8e\u76ee\u6807\u8ba1\u7b97\u673a\u79ef\u6781\u62d2\u7edd\uff0c\u65e0\u6cd5\u8fde\u63a5\u3002&amp;#x27;)&amp;#x27;: /wd/hub/session\nDEBUG    urllib3.connectionpool:connectionpool.py:246 Starting new HTTP connection (4): 127.0.0.1:4723\n&#34;}]}, &#34;renderCollapsed&#34;: [&#34;passed&#34;], &#34;initialSort&#34;: &#34;result&#34;, &#34;title&#34;: &#34;baogao.html&#34;}"></div>
    <script>
      (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
const { getCollapsedCategory, setCollapsedIds } = require('./storage.js')

class DataManager {
    setManager(data) {
        const collapsedCategories = [...getCollapsedCategory(data.renderCollapsed)]
        const collapsedIds = []
        const tests = Object.values(data.tests).flat().map((test, index) => {
            const collapsed = collapsedCategories.includes(test.result.toLowerCase())
            const id = `test_${index}`
            if (collapsed) {
                collapsedIds.push(id)
            }
            return {
                ...test,
                id,
                collapsed,
            }
        })
        const dataBlob = { ...data, tests }
        this.data = { ...dataBlob }
        this.renderData = { ...dataBlob }
        setCollapsedIds(collapsedIds)
    }

    get allData() {
        return { ...this.data }
    }

    resetRender() {
        this.renderData = { ...this.data }
    }

    setRender(data) {
        this.renderData.tests = [...data]
    }

    toggleCollapsedItem(id) {
        this.renderData.tests = this.renderData.tests.map((test) =>
            test.id === id ? { ...test, collapsed: !test.collapsed } : test,
        )
    }

    set allCollapsed(collapsed) {
        this.renderData = { ...this.renderData, tests: [...this.renderData.tests.map((test) => (
            { ...test, collapsed }
        ))] }
    }

    get testSubset() {
        return [...this.renderData.tests]
    }

    get environment() {
        return this.renderData.environment
    }

    get initialSort() {
        return this.data.initialSort
    }
}

module.exports = {
    manager: new DataManager(),
}

},{"./storage.js":8}],2:[function(require,module,exports){
const mediaViewer = require('./mediaviewer.js')
const templateEnvRow = document.getElementById('template_environment_row')
const templateResult = document.getElementById('template_results-table__tbody')

function htmlToElements(html) {
    const temp = document.createElement('template')
    temp.innerHTML = html
    return temp.content.childNodes
}

const find = (selector, elem) => {
    if (!elem) {
        elem = document
    }
    return elem.querySelector(selector)
}

const findAll = (selector, elem) => {
    if (!elem) {
        elem = document
    }
    return [...elem.querySelectorAll(selector)]
}

const dom = {
    getStaticRow: (key, value) => {
        const envRow = templateEnvRow.content.cloneNode(true)
        const isObj = typeof value === 'object' && value !== null
        const values = isObj ? Object.keys(value).map((k) => `${k}: ${value[k]}`) : null

        const valuesElement = htmlToElements(
            values ? `<ul>${values.map((val) => `<li>${val}</li>`).join('')}<ul>` : `<div>${value}</div>`)[0]
        const td = findAll('td', envRow)
        td[0].textContent = key
        td[1].appendChild(valuesElement)

        return envRow
    },
    getResultTBody: ({ testId, id, log, extras, resultsTableRow, tableHtml, result, collapsed }) => {
        const resultBody = templateResult.content.cloneNode(true)
        resultBody.querySelector('tbody').classList.add(result.toLowerCase())
        resultBody.querySelector('tbody').id = testId
        resultBody.querySelector('.collapsible').dataset.id = id

        resultsTableRow.forEach((html) => {
            const t = document.createElement('template')
            t.innerHTML = html
            resultBody.querySelector('.collapsible').appendChild(t.content)
        })

        if (log) {
            // Wrap lines starting with "E" with span.error to color those lines red
            const wrappedLog = log.replace(/^E.*$/gm, (match) => `<span class="error">${match}</span>`)
            resultBody.querySelector('.log').innerHTML = wrappedLog
        } else {
            resultBody.querySelector('.log').remove()
        }

        if (collapsed) {
            resultBody.querySelector('.collapsible > td')?.classList.add('collapsed')
            resultBody.querySelector('.extras-row').classList.add('hidden')
        } else {
            resultBody.querySelector('.collapsible > td')?.classList.remove('collapsed')
        }

        const media = []
        extras?.forEach(({ name, format_type, content }) => {
            if (['image', 'video'].includes(format_type)) {
                media.push({ path: content, name, format_type })
            }

            if (format_type === 'html') {
                resultBody.querySelector('.extraHTML').insertAdjacentHTML('beforeend', `<div>${content}</div>`)
            }
        })
        mediaViewer.setup(resultBody, media)

        // Add custom html from the pytest_html_results_table_html hook
        tableHtml?.forEach((item) => {
            resultBody.querySelector('td[class="extra"]').insertAdjacentHTML('beforeend', item)
        })

        return resultBody
    },
}

module.exports = {
    dom,
    htmlToElements,
    find,
    findAll,
}

},{"./mediaviewer.js":6}],3:[function(require,module,exports){
const { manager } = require('./datamanager.js')
const { doSort } = require('./sort.js')
const storageModule = require('./storage.js')

const getFilteredSubSet = (filter) =>
    manager.allData.tests.filter(({ result }) => filter.includes(result.toLowerCase()))

const doInitFilter = () => {
    const currentFilter = storageModule.getVisible()
    const filteredSubset = getFilteredSubSet(currentFilter)
    manager.setRender(filteredSubset)
}

const doFilter = (type, show) => {
    if (show) {
        storageModule.showCategory(type)
    } else {
        storageModule.hideCategory(type)
    }

    const currentFilter = storageModule.getVisible()
    const filteredSubset = getFilteredSubSet(currentFilter)
    manager.setRender(filteredSubset)

    const sortColumn = storageModule.getSort()
    doSort(sortColumn, true)
}

module.exports = {
    doFilter,
    doInitFilter,
}

},{"./datamanager.js":1,"./sort.js":7,"./storage.js":8}],4:[function(require,module,exports){
const { redraw, bindEvents, renderStatic } = require('./main.js')
const { doInitFilter } = require('./filter.js')
const { doInitSort } = require('./sort.js')
const { manager } = require('./datamanager.js')
const data = JSON.parse(document.getElementById('data-container').dataset.jsonblob)

function init() {
    manager.setManager(data)
    doInitFilter()
    doInitSort()
    renderStatic()
    redraw()
    bindEvents()
}

init()

},{"./datamanager.js":1,"./filter.js":3,"./main.js":5,"./sort.js":7}],5:[function(require,module,exports){
const { dom, find, findAll } = require('./dom.js')
const { manager } = require('./datamanager.js')
const { doSort } = require('./sort.js')
const { doFilter } = require('./filter.js')
const {
    getVisible,
    getCollapsedIds,
    setCollapsedIds,
    getSort,
    getSortDirection,
    possibleFilters,
} = require('./storage.js')

const removeChildren = (node) => {
    while (node.firstChild) {
        node.removeChild(node.firstChild)
    }
}

const renderStatic = () => {
    const renderEnvironmentTable = () => {
        const environment = manager.environment
        const rows = Object.keys(environment).map((key) => dom.getStaticRow(key, environment[key]))
        const table = document.getElementById('environment')
        removeChildren(table)
        rows.forEach((row) => table.appendChild(row))
    }
    renderEnvironmentTable()
}

const addItemToggleListener = (elem) => {
    elem.addEventListener('click', ({ target }) => {
        const id = target.parentElement.dataset.id
        manager.toggleCollapsedItem(id)

        const collapsedIds = getCollapsedIds()
        if (collapsedIds.includes(id)) {
            const updated = collapsedIds.filter((item) => item !== id)
            setCollapsedIds(updated)
        } else {
            collapsedIds.push(id)
            setCollapsedIds(collapsedIds)
        }
        redraw()
    })
}

const renderContent = (tests) => {
    const sortAttr = getSort(manager.initialSort)
    const sortAsc = JSON.parse(getSortDirection())
    const rows = tests.map(dom.getResultTBody)
    const table = document.getElementById('results-table')
    const tableHeader = document.getElementById('results-table-head')

    const newTable = document.createElement('table')
    newTable.id = 'results-table'

    // remove all sorting classes and set the relevant
    findAll('.sortable', tableHeader).forEach((elem) => elem.classList.remove('asc', 'desc'))
    tableHeader.querySelector(`.sortable[data-column-type="${sortAttr}"]`)?.classList.add(sortAsc ? 'desc' : 'asc')
    newTable.appendChild(tableHeader)

    if (!rows.length) {
        const emptyTable = document.getElementById('template_results-table__body--empty').content.cloneNode(true)
        newTable.appendChild(emptyTable)
    } else {
        rows.forEach((row) => {
            if (!!row) {
                findAll('.collapsible td:not(.col-links', row).forEach(addItemToggleListener)
                find('.logexpander', row).addEventListener('click',
                    (evt) => evt.target.parentNode.classList.toggle('expanded'),
                )
                newTable.appendChild(row)
            }
        })
    }

    table.replaceWith(newTable)
}

const renderDerived = () => {
    const currentFilter = getVisible()
    possibleFilters.forEach((result) => {
        const input = document.querySelector(`input[data-test-result="${result}"]`)
        input.checked = currentFilter.includes(result)
    })
}

const bindEvents = () => {
    const filterColumn = (evt) => {
        const { target: element } = evt
        const { testResult } = element.dataset

        doFilter(testResult, element.checked)
        const collapsedIds = getCollapsedIds()
        const updated = manager.renderData.tests.map((test) => {
            return {
                ...test,
                collapsed: collapsedIds.includes(test.id),
            }
        })
        manager.setRender(updated)
        redraw()
    }

    const header = document.getElementById('environment-header')
    header.addEventListener('click', () => {
        const table = document.getElementById('environment')
        table.classList.toggle('hidden')
        header.classList.toggle('collapsed')
    })

    findAll('input[name="filter_checkbox"]').forEach((elem) => {
        elem.addEventListener('click', filterColumn)
    })

    findAll('.sortable').forEach((elem) => {
        elem.addEventListener('click', (evt) => {
            const { target: element } = evt
            const { columnType } = element.dataset
            doSort(columnType)
            redraw()
        })
    })

    document.getElementById('show_all_details').addEventListener('click', () => {
        manager.allCollapsed = false
        setCollapsedIds([])
        redraw()
    })
    document.getElementById('hide_all_details').addEventListener('click', () => {
        manager.allCollapsed = true
        const allIds = manager.renderData.tests.map((test) => test.id)
        setCollapsedIds(allIds)
        redraw()
    })
}

const redraw = () => {
    const { testSubset } = manager

    renderContent(testSubset)
    renderDerived()
}

module.exports = {
    redraw,
    bindEvents,
    renderStatic,
}

},{"./datamanager.js":1,"./dom.js":2,"./filter.js":3,"./sort.js":7,"./storage.js":8}],6:[function(require,module,exports){
class MediaViewer {
    constructor(assets) {
        this.assets = assets
        this.index = 0
    }

    nextActive() {
        this.index = this.index === this.assets.length - 1 ? 0 : this.index + 1
        return [this.activeFile, this.index]
    }

    prevActive() {
        this.index = this.index === 0 ? this.assets.length - 1 : this.index -1
        return [this.activeFile, this.index]
    }

    get currentIndex() {
        return this.index
    }

    get activeFile() {
        return this.assets[this.index]
    }
}


const setup = (resultBody, assets) => {
    if (!assets.length) {
        resultBody.querySelector('.media').classList.add('hidden')
        return
    }

    const mediaViewer = new MediaViewer(assets)
    const container = resultBody.querySelector('.media-container')
    const leftArrow = resultBody.querySelector('.media-container__nav--left')
    const rightArrow = resultBody.querySelector('.media-container__nav--right')
    const mediaName = resultBody.querySelector('.media__name')
    const counter = resultBody.querySelector('.media__counter')
    const imageEl = resultBody.querySelector('img')
    const sourceEl = resultBody.querySelector('source')
    const videoEl = resultBody.querySelector('video')

    const setImg = (media, index) => {
        if (media?.format_type === 'image') {
            imageEl.src = media.path

            imageEl.classList.remove('hidden')
            videoEl.classList.add('hidden')
        } else if (media?.format_type === 'video') {
            sourceEl.src = media.path

            videoEl.classList.remove('hidden')
            imageEl.classList.add('hidden')
        }

        mediaName.innerText = media?.name
        counter.innerText = `${index + 1} / ${assets.length}`
    }
    setImg(mediaViewer.activeFile, mediaViewer.currentIndex)

    const moveLeft = () => {
        const [media, index] = mediaViewer.prevActive()
        setImg(media, index)
    }
    const doRight = () => {
        const [media, index] = mediaViewer.nextActive()
        setImg(media, index)
    }
    const openImg = () => {
        window.open(mediaViewer.activeFile.path, '_blank')
    }
    if (assets.length === 1) {
        container.classList.add('media-container--fullscreen')
    } else {
        leftArrow.addEventListener('click', moveLeft)
        rightArrow.addEventListener('click', doRight)
    }
    imageEl.addEventListener('click', openImg)
}

module.exports = {
    setup,
}

},{}],7:[function(require,module,exports){
const { manager } = require('./datamanager.js')
const storageModule = require('./storage.js')

const genericSort = (list, key, ascending, customOrder) => {
    let sorted
    if (customOrder) {
        sorted = list.sort((a, b) => {
            const aValue = a.result.toLowerCase()
            const bValue = b.result.toLowerCase()

            const aIndex = customOrder.findIndex((item) => item.toLowerCase() === aValue)
            const bIndex = customOrder.findIndex((item) => item.toLowerCase() === bValue)

            // Compare the indices to determine the sort order
            return aIndex - bIndex
        })
    } else {
        sorted = list.sort((a, b) => a[key] === b[key] ? 0 : a[key] > b[key] ? 1 : -1)
    }

    if (ascending) {
        sorted.reverse()
    }
    return sorted
}

const durationSort = (list, ascending) => {
    const parseDuration = (duration) => {
        if (duration.includes(':')) {
            // If it's in the format "HH:mm:ss"
            const [hours, minutes, seconds] = duration.split(':').map(Number)
            return (hours * 3600 + minutes * 60 + seconds) * 1000
        } else {
            // If it's in the format "nnn ms"
            return parseInt(duration)
        }
    }
    const sorted = list.sort((a, b) => parseDuration(a['duration']) - parseDuration(b['duration']))
    if (ascending) {
        sorted.reverse()
    }
    return sorted
}

const doInitSort = () => {
    const type = storageModule.getSort(manager.initialSort)
    const ascending = storageModule.getSortDirection()
    const list = manager.testSubset
    const initialOrder = ['Error', 'Failed', 'Rerun', 'XFailed', 'XPassed', 'Skipped', 'Passed']

    storageModule.setSort(type)
    storageModule.setSortDirection(ascending)

    if (type?.toLowerCase() === 'original') {
        manager.setRender(list)
    } else {
        let sortedList
        switch (type) {
        case 'duration':
            sortedList = durationSort(list, ascending)
            break
        case 'result':
            sortedList = genericSort(list, type, ascending, initialOrder)
            break
        default:
            sortedList = genericSort(list, type, ascending)
            break
        }
        manager.setRender(sortedList)
    }
}

const doSort = (type, skipDirection) => {
    const newSortType = storageModule.getSort(manager.initialSort) !== type
    const currentAsc = storageModule.getSortDirection()
    let ascending
    if (skipDirection) {
        ascending = currentAsc
    } else {
        ascending = newSortType ? false : !currentAsc
    }
    storageModule.setSort(type)
    storageModule.setSortDirection(ascending)

    const list = manager.testSubset
    const sortedList = type === 'duration' ? durationSort(list, ascending) : genericSort(list, type, ascending)
    manager.setRender(sortedList)
}

module.exports = {
    doInitSort,
    doSort,
}

},{"./datamanager.js":1,"./storage.js":8}],8:[function(require,module,exports){
const possibleFilters = [
    'passed',
    'skipped',
    'failed',
    'error',
    'xfailed',
    'xpassed',
    'rerun',
]

const getVisible = () => {
    const url = new URL(window.location.href)
    const settings = new URLSearchParams(url.search).get('visible')
    const lower = (item) => {
        const lowerItem = item.toLowerCase()
        if (possibleFilters.includes(lowerItem)) {
            return lowerItem
        }
        return null
    }
    return settings === null ?
        possibleFilters :
        [...new Set(settings?.split(',').map(lower).filter((item) => item))]
}

const hideCategory = (categoryToHide) => {
    const url = new URL(window.location.href)
    const visibleParams = new URLSearchParams(url.search).get('visible')
    const currentVisible = visibleParams ? visibleParams.split(',') : [...possibleFilters]
    const settings = [...new Set(currentVisible)].filter((f) => f !== categoryToHide).join(',')

    url.searchParams.set('visible', settings)
    window.history.pushState({}, null, unescape(url.href))
}

const showCategory = (categoryToShow) => {
    if (typeof window === 'undefined') {
        return
    }
    const url = new URL(window.location.href)
    const currentVisible = new URLSearchParams(url.search).get('visible')?.split(',').filter(Boolean) ||
        [...possibleFilters]
    const settings = [...new Set([categoryToShow, ...currentVisible])]
    const noFilter = possibleFilters.length === settings.length || !settings.length

    noFilter ? url.searchParams.delete('visible') : url.searchParams.set('visible', settings.join(','))
    window.history.pushState({}, null, unescape(url.href))
}

const getSort = (initialSort) => {
    const url = new URL(window.location.href)
    let sort = new URLSearchParams(url.search).get('sort')
    if (!sort) {
        sort = initialSort || 'result'
    }
    return sort
}

const setSort = (type) => {
    const url = new URL(window.location.href)
    url.searchParams.set('sort', type)
    window.history.pushState({}, null, unescape(url.href))
}

const getCollapsedCategory = (renderCollapsed) => {
    let categories
    if (typeof window !== 'undefined') {
        const url = new URL(window.location.href)
        const collapsedItems = new URLSearchParams(url.search).get('collapsed')
        switch (true) {
        case !renderCollapsed && collapsedItems === null:
            categories = ['passed']
            break
        case collapsedItems?.length === 0 || /^["']{2}$/.test(collapsedItems):
            categories = []
            break
        case /^all$/.test(collapsedItems) || collapsedItems === null && /^all$/.test(renderCollapsed):
            categories = [...possibleFilters]
            break
        default:
            categories = collapsedItems?.split(',').map((item) => item.toLowerCase()) || renderCollapsed
            break
        }
    } else {
        categories = []
    }
    return categories
}

const getSortDirection = () => JSON.parse(sessionStorage.getItem('sortAsc')) || false
const setSortDirection = (ascending) => sessionStorage.setItem('sortAsc', ascending)

const getCollapsedIds = () => JSON.parse(sessionStorage.getItem('collapsedIds')) || []
const setCollapsedIds = (list) => sessionStorage.setItem('collapsedIds', JSON.stringify(list))

module.exports = {
    getVisible,
    hideCategory,
    showCategory,
    getCollapsedIds,
    setCollapsedIds,
    getSort,
    setSort,
    getSortDirection,
    setSortDirection,
    getCollapsedCategory,
    possibleFilters,
}

},{}]},{},[4]);
    </script>
  </footer>
</html>